<?php

namespace app\checkin\model;

use think\admin\Model;

/**
 * 门禁设备模型
 */
class Device extends Model
{
    /**
     * 数据表名
     * @var string
     */
    protected $name = 'checkin_device';
    
    /**
     * 自动时间戳
     * @var bool
     */
    protected $autoWriteTimestamp = true;
    
    /**
     * JSON字段
     * @var array
     */
    protected $json = ['config'];
    
    /**
     * 设备类型数据
     * @var array
     */
    public static $typeMap = [
        'face' => '人脸识别',
        'card' => '刷卡识别',
        'mixed' => '混合识别',
    ];
    
    /**
     * 状态数据
     * @var array
     */
    public static $statusMap = [
        0 => '禁用',
        1 => '启用',
    ];
    
    /**
     * 在线状态数据
     * @var array
     */
    public static $onlineStatusMap = [
        0 => '离线',
        1 => '在线',
    ];
    
    /**
     * 获取设备类型文本
     * @param $value
     * @param $data
     * @return string
     */
    public function getTypeTextAttr($value, $data)
    {
        return self::$typeMap[$data['device_type']] ?? '未知';
    }
    
    /**
     * 获取状态文本
     * @param $value
     * @param $data
     * @return string
     */
    public function getStatusTextAttr($value, $data)
    {
        return self::$statusMap[$data['status']] ?? '未知';
    }
    
    /**
     * 获取在线状态文本
     * @param $value
     * @param $data
     * @return string
     */
    public function getOnlineStatusTextAttr($value, $data)
    {
        return self::$onlineStatusMap[$data['online_status']] ?? '未知';
    }
    
    /**
     * 关联门店
     * @return \think\model\relation\HasOne
     */
    public function store()
    {
        return $this->hasOne(Store::class, 'id', 'store_id')->bind(['store_name' => 'name']);
    }
    
    /**
     * 验证设备登录
     * @param string $sn 设备序列号
     * @param string $sign 签名
     * @param int $timestamp 时间戳
     * @return array
     */
    public static function verifyLogin(string $sn, string $sign, int $timestamp): array
    {
        // 查找设备
        $device = self::mk()->where(['sn' => $sn])->findOrEmpty();
        if ($device->isEmpty()) {
            return ['code' => 1002, 'msg' => '设备不存在'];
        }
        
        // 检查设备状态
        if (intval($device->getAttr('status')) !== 1) {
            return ['code' => 1003, 'msg' => '设备已禁用'];
        }
        
        // 验证签名
        $passwd = strval($device->getAttr('passwd'));
        $expectedSign = md5($sn . $passwd . $timestamp);
        
        if (!hash_equals($expectedSign, $sign)) {
            return ['code' => 1001, 'msg' => '签名验证失败'];
        }
        
        // 检查时间戳（允许5分钟误差）
        $currentTime = time();
        if (abs($currentTime - $timestamp) > 300) {
            return ['code' => 1005, 'msg' => '时间戳无效'];
        }
        
        // 更新设备登录信息
        $device->save([
            'last_login_time' => date('Y-m-d H:i:s'),
            'online_status' => 1,
        ]);
        
        return ['code' => 200, 'msg' => '登录成功', 'device' => $device->toArray()];
    }
    
    /**
     * 更新设备心跳
     * @param string $sn 设备序列号
     * @return bool
     */
    public static function updateHeartbeat(string $sn): bool
    {
        $device = self::mk()->where(['sn' => $sn])->findOrEmpty();
        if ($device->isEmpty()) {
            return false;
        }
        
        $device->save([
            'last_heartbeat_time' => date('Y-m-d H:i:s'),
            'online_status' => 1,
        ]);
        
        return true;
    }
    
    /**
     * 生成设备密码
     * @param string $sn 设备序列号
     * @return string
     */
    public static function generatePassword(string $sn): string
    {
        return md5($sn . time() . rand(1000, 9999));
    }
}
